package com.tengju.bff.interfaces.covercharge.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.idanchuang.component.base.util.StringUtil;
import com.idanchuang.component.config.apollo.util.ConfigUtil;
import com.tengju.bff.interfaces.covercharge.constant.*;
import com.tengju.bff.interfaces.covercharge.entity.po.*;
import com.tengju.bff.interfaces.covercharge.entity.vo.*;
import com.tengju.bff.interfaces.covercharge.enums.ProfitTypeEnum;
import com.tengju.bff.interfaces.covercharge.mapper.CustPaidTransMapper;
import com.tengju.bff.interfaces.covercharge.mapper.ServiceSelfCertificationWithdrawMapper;
import com.tengju.bff.interfaces.covercharge.service.*;
import com.tengju.bff.interfaces.covercharge.util.NumberToCN;
import com.tengju.bff.interfaces.covercharge.util.alarmUtil.MsgSendUtil;
import com.tengju.bff.interfaces.covercharge.util.redis.HeavyUtil;
import com.tengju.payment.application.shard.ApplicationException;
import com.tengju.payment.application.shard.ApplicationExceptionCode;
import com.tengju.payment.application.transfer.TransferService;
import com.tengju.payment.domain.model.AccountType;
import com.tengju.payment.domain.model.TradeStatus;
import com.tengju.payment.domain.model.transfer.*;
import com.tengju.payment.domain.shard.Amount;
import com.tengju.payment.domain.shard.DoubleCalculator;
import com.tengju.payment.domain.shard.JsonUtil;
import com.tengju.settlement.domain.model.account.AccountId;
import com.tengju.settlement.domain.model.depository.*;
import com.tengju.user.application.sms.SmsBizService;
import com.tengju.user.domain.model.user.UserIdCode;
import com.tengju.user.domain.model.user.UserInfo;
import com.tengju.user.domain.service.UserDocService;
import com.zoi7.component.core.exception.ServiceException;
import io.reactivex.rxjava3.core.Maybe;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 自认证用户提现表 服务实现类
 * </p>
 *
 * @author zhaoyi
 * @since 2020-02-26
 */
@Service
@Slf4j
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class ServiceSelfCertificationWithdrawServiceImpl extends ServiceImpl<ServiceSelfCertificationWithdrawMapper, ServiceSelfCertificationWithdraw> implements IServiceSelfCertificationWithdrawService {

    //线程最大处理数
    private final static Integer SPLIT_MAX_NUM = 1000;
    private static final long PAGE_SIZE = 10000;

    private final ServiceSelfCertificationWithdrawMapper serviceSelfCertificationWithdrawMapper;
    private final UserService userService;
    private final IServiceAccountService serviceAccountService;
    private final ICustPaidTransService custPaidTransService;
    private final TransferService transferService;
    private final ICustTaskQueueService custTaskQueueService;
    private final IServiceSelfCertificationService serviceSelfCertificationService;
    private final ThreadPoolExecutor threadPoolExecutor;
    private final IServiceFrozenDetailService serviceFrozenDetailService;
    private final SmsBizService smsBizService;
    private final UserDocService userDocService;
    private final ICustPaidTransService iCustPaidTransService;
    private final DepositoryAccountRepository depositoryAccountRepository;
    private final DepositoryBankCardRepository depositoryBankCardRepository;
    private final CustPaidTransMapper custPaidTransMapper;

    @Value("${system.env}")
    String env;

    @Value("${self.certification.withdraw.print.application.platform}")
    String printApplicationPlatform;
    @Value("${self.certification.withdraw.print.application.department}")
    String printApplicationDepartment;

    @Value("${depository.account.whiteList}")
    private String DepAccountWhiteList;

    @Override
    public List<WithdrawRecordVo> getWithdrawList(Integer idCode, String platformCode, Integer type, String dateTime) {
        List<WithdrawRecordVo> lists = serviceSelfCertificationWithdrawMapper.getWithdrawList(idCode, platformCode, type, dateTime);
        for (WithdrawRecordVo vo : lists) {
            SelfWithdrawStatusEnum statusEnum = SelfWithdrawStatusEnum.getStatusDesc(vo.getStatus());
            vo.setStatusName(Objects.isNull(statusEnum) ? null : statusEnum.getDesc());
            if (SelfCertificationTypeEnum.SINGLE.getCode().equals(type)) {
                vo.setIdentity(CooperationEnum.CERTIFIEDINDIVIDUAL.getCode());
            } else if (SelfCertificationTypeEnum.COMPANY.getCode().equals(type)) {
                vo.setIdentity(CooperationEnum.CERTIFIEDBUSINESS.getCode());
            }

        }
        return lists;
    }

    @Override
    public List<AdminSelfCertificationQueryVo> withdrawListByTime(Integer idCode, String platformCode, Integer type, String startTime, String endTime) {
        List<AdminSelfCertificationQueryVo> lists = serviceSelfCertificationWithdrawMapper.withdrawListByTime(idCode, platformCode, type, startTime, endTime);
        return lists;
    }

    @Override
    public BigDecimal getIssuedAmount(Integer idCode, String platformCode, Integer type, String dateTime) {
        return serviceSelfCertificationWithdrawMapper.getIssuedAmount(idCode, platformCode, type, dateTime);
    }

    @Override
    public BigDecimal getBeIssuedAmount(Integer idCode, String platformCode, Integer type, String dateTime) {
        return serviceSelfCertificationWithdrawMapper.getBeIssuedAmount(idCode, platformCode, type, dateTime);
    }

    @Override
    public Page<AdminSelfCertificationQueryVo> queryPageCertification(Page page, String idCode, String name, Integer invoice, String platformCode, Integer status, String startDate, String endDate, Integer type, String exportType) {
        List<AdminSelfCertificationQueryVo> querylist = serviceSelfCertificationWithdrawMapper.queryPageCertification(page, idCode, name, invoice, platformCode, status, startDate, endDate, type, exportType);
        List<String> reqSnList = new ArrayList<>();
        List<UserIdCode> idList = new ArrayList<>();
        for (AdminSelfCertificationQueryVo log : querylist) {
            idList.add(new UserIdCode(log.getIdCode()));
            reqSnList.add(log.getReqSn());
        }
        Map<UserIdCode, UserInfo> userMap = userService.queryUserMap(idList);
        List<CustPaidTrans> custPaidTransList = custPaidTransMapper.getByReqSns(reqSnList);
        Map<String, CustPaidTrans> custPaidTransMap = custPaidTransList.stream()
                .collect(Collectors.toMap(CustPaidTrans::getReqSn, Function.identity()));
//
//        List<DepositoryBankCard> depositoryBankCards = depositoryBankCardRepository.getByIdCodesStatus(idList.stream().map(UserIdCode::getValue)
//                .map(com.tengju.settlement.domain.model.account.UserIdCode::new).collect(Collectors.toList()), List.of(BindStatus.SUCCESS));
//        Map<UserIdCode, DepositoryBankCard> depositoryBankCardMap = depositoryBankCards.stream()
//                .collect(Collectors.toMap(depositoryBankCard -> new UserIdCode(depositoryBankCard.getIdCode().getValue()), Function.identity()));

        List<DepositoryAccount> pingAnDepositoryAccounts = depositoryAccountRepository.getByIdCodesStatusNormal(idList.stream().map(UserIdCode::getValue)
                .map(com.tengju.settlement.domain.model.account.UserIdCode::new).collect(Collectors.toList()),DepositoryChannel.PING_AN);
        List<DepositoryAccountId> pingAnDepositoryAccountIds = pingAnDepositoryAccounts
                .stream().map(DepositoryAccount::getDepositoryAccountId).collect(Collectors.toList());
        List<DepositoryAccount> internalDepositoryAccounts = depositoryAccountRepository.getByIdCodesStatusNormal(idList.stream().map(UserIdCode::getValue)
                .map(com.tengju.settlement.domain.model.account.UserIdCode::new).collect(Collectors.toList()),DepositoryChannel.INTERNAL);
        List<DepositoryAccountId> internalDepositoryAccountIds = internalDepositoryAccounts
                .stream().map(DepositoryAccount::getDepositoryAccountId).collect(Collectors.toList());

        Map<UserIdCode, DepositoryBankCard> pingAnDepositoryBankCardMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(pingAnDepositoryAccountIds)) {
            List<DepositoryBankCard> pingAnDepositoryBankCards = depositoryBankCardRepository
                    .getByDepositoryAccountIdsStatus(pingAnDepositoryAccountIds, List.of(BindStatus.SUCCESS));
            pingAnDepositoryBankCardMap = pingAnDepositoryBankCards.stream()
                    .collect(Collectors.toMap(depositoryBankCard -> new UserIdCode(depositoryBankCard.getIdCode().getValue()), Function.identity()));
        }


        Map<UserIdCode, DepositoryBankCard> internalDepositoryBankCardMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(internalDepositoryAccountIds)) {
            List<DepositoryBankCard> internalDepositoryBankCards = depositoryBankCardRepository
                    .getByDepositoryAccountIdsStatus(internalDepositoryAccountIds, List.of(BindStatus.SUCCESS));
            internalDepositoryBankCardMap = internalDepositoryBankCards.stream()
                    .collect(Collectors.toMap(depositoryBankCard -> new UserIdCode(depositoryBankCard.getIdCode().getValue()), Function.identity()));
        }




        for (AdminSelfCertificationQueryVo query : querylist) {
            SelfCertificationWithdrawExtra extra = null;
            if (!StringUtil.isEmpty(query.getExtra())) {
                extra = JsonUtil.toObject(query.getExtra(), SelfCertificationWithdrawExtra.class);
            }
            query.setChannel(Optional.ofNullable(extra)
                    .map(SelfCertificationWithdrawExtra::getChannel).map(DepositoryChannel::getDesc).orElse(""));
            CustPaidTrans custPaidTrans = custPaidTransMap.get(query.getReqSn());
            DepositoryBankCard depositoryBankCard;

            if (extra != null && extra.getChannel() == DepositoryChannel.INTERNAL) {
                depositoryBankCard = internalDepositoryBankCardMap.get(new UserIdCode(query.getIdCode()));
            } else {
                depositoryBankCard = pingAnDepositoryBankCardMap.get(new UserIdCode(query.getIdCode()));
            }

            if (SelfWithdrawStatusEnum.APPLY.getCode().equals(query.getStatus())
                    || SelfWithdrawStatusEnum.FPASS.getCode().equals(query.getStatus())
                    || SelfWithdrawStatusEnum.FREJECT.getCode().equals(query.getStatus())
                    || SelfWithdrawStatusEnum.CANCEL.getCode().equals(query.getStatus())
                    || SelfWithdrawStatusEnum.SREJECT.getCode().equals(query.getStatus())
                    || SelfWithdrawStatusEnum.SPASS.getCode().equals(query.getStatus())
                    || SelfWithdrawStatusEnum.IN_DISTRIBUT.getCode().equals(query.getStatus())
                    || SelfWithdrawStatusEnum.SEND.getCode().equals(query.getStatus())) {
                query.setBankName(Optional.ofNullable(depositoryBankCard).map(DepositoryBankCard::getBankName).orElse(""));
                query.setBankNo(Optional.ofNullable(depositoryBankCard).map(DepositoryBankCard::getCardNo).orElse(""));
            } else {
                query.setBankName(Optional.ofNullable(custPaidTrans).map(CustPaidTrans::getOpenBank).orElse(""));
                query.setBankNo(Optional.ofNullable(custPaidTrans).map(CustPaidTrans::getAccountNo).orElse(""));
                query.setIdcardName(Optional.ofNullable(custPaidTrans).map(CustPaidTrans::getAccountName).orElse(""));
            }
            UserIdCode userId = new UserIdCode(query.getIdCode());
            if (userMap.containsKey(userId)) {
                UserInfo userVO = userMap.get(userId);
                query.setMobile(userVO.getMobile());
                query.setName(userVO.getName());
            }
        }
        page.setRecords(querylist);
        return page;
    }


    @Override
    public Boolean isExistSelfCertWithdraw(Long idCode) {
        QueryWrapper<ServiceSelfCertificationWithdraw> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id_code", idCode);
        queryWrapper.notIn("status", SelfWithdrawStatusEnum.CANCEL.getCode(), SelfWithdrawStatusEnum.SUCCESS.getCode());
        List<ServiceSelfCertificationWithdraw> lists = serviceSelfCertificationWithdrawMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(lists)) {
            return Boolean.FALSE;
        }
        return lists.size() > 0;
    }

    @Override
    public PlayWithConfirmationPreviewVo getTotalAmountWithList(List<Integer> cycleAddIdList) {
        List<ServiceSelfCertificationWithdraw> querylist = serviceSelfCertificationWithdrawMapper.queryPageCertificationPaidWithList(cycleAddIdList);
        List<Long> idList = new ArrayList<>();
        BigDecimal amount = BigDecimal.ZERO;
        for (ServiceSelfCertificationWithdraw record : querylist) {
            amount = amount.add(record.getMoney());
        }
        PlayWithConfirmationPreviewVo playWithConfirmationPreviewVo = new PlayWithConfirmationPreviewVo();
        playWithConfirmationPreviewVo.setSelectNumberOf(String.valueOf(querylist.size()));
        playWithConfirmationPreviewVo.setAggregateAmount(String.valueOf(amount));

        return playWithConfirmationPreviewVo;
    }

    @Override
    public PlayWithConfirmationPreviewVo getTotalAmountWithAll() {
        QueryWrapper<ServiceSelfCertificationWithdraw> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", SelfWithdrawStatusEnum.SPASS.getCode());
        //查询符合条件的周期记录总数
        Integer count = this.baseMapper.selectCount(queryWrapper);
        //获取页数
        int page = Math.toIntExact((count / PAGE_SIZE + (count % PAGE_SIZE > 0 ? 1 : 0)));
        BigDecimal amount = BigDecimal.ZERO;
        Integer size = 0;
        //分页获取符合条件页数
        for (int i = 1; i <= page; i++) {
            Page<ServiceSelfCertificationWithdraw> pageResult = this.baseMapper.selectPage(new Page<>(i, PAGE_SIZE), queryWrapper);
            List<ServiceSelfCertificationWithdraw> list = pageResult.getRecords();
            if (!org.apache.commons.collections.CollectionUtils.isEmpty(list)) {
                for (ServiceSelfCertificationWithdraw record : list) {
                    amount = amount.add(record.getMoney());
                }
                size += list.size();
            }
        }

        PlayWithConfirmationPreviewVo playWithConfirmationPreviewVo = new PlayWithConfirmationPreviewVo();
        playWithConfirmationPreviewVo.setSelectNumberOf(String.valueOf(size));
        playWithConfirmationPreviewVo.setAggregateAmount(String.valueOf(amount));

        return playWithConfirmationPreviewVo;
    }

    /**
     * 查询批量列表
     *
     * @param cycleAddIds
     * @return
     */
    @Override
    public List<ServiceSelfCertificationWithdraw> queryPaidBatchList(List<Integer> cycleAddIds) {
        QueryWrapper<ServiceSelfCertificationWithdraw> qw = new QueryWrapper<>();
        qw.in("id", cycleAddIds);
        qw.eq("status", SelfWithdrawStatusEnum.SPASS.getCode());

        return this.baseMapper.selectList(qw);
    }

    /**
     * 批量发放提现
     *
     * @param serviceSelfCertificationWithdrawList
     * @param approvers
     * @return
     */
    @Override
    public String batchProcessingWithdrawalRecordPaid(List<ServiceSelfCertificationWithdraw> serviceSelfCertificationWithdrawList, String approvers) {

        return this.withdrawalInsertTim(serviceSelfCertificationWithdrawList, approvers);
//        CashBackRes step = null;
//        StringBuilder errorMsg = new StringBuilder();
//        for (ServiceSelfCertificationWithdraw serviceSelfCertificationWithdraw : serviceSelfCertificationWithdrawList)
//        {
//            try {
//                if(HeavyUtil.isRun(HeavyKeyEnum.WITHDRAWAL_REQUEST.getCode() + serviceSelfCertificationWithdraw.getId())){
//                    errorMsg.append("提现序号:").append(serviceSelfCertificationWithdraw.getId()).append(",提现处理时出现错误:").append("该笔正在被处理").append(";");
//                } else {
//                    step = this.doWithdraw(serviceSelfCertificationWithdraw.getId(), approvers, false);
//                    if(step != null && !"".equals(step.getErrorMessage())) {
//                        errorMsg.append("提现序号:").append(serviceSelfCertificationWithdraw.getId()).append(",提现处理时出现错误:").append(step.getErrorMessage()).append(";");
//                    }
//                    step = null;
//                }
//            } catch (Exception e) {
//                log.error("自认证批量提现出现未知错误:", e);
//                if(step != null && !"".equals(step.getErrorMessage())) {
//                    errorMsg.append("提现序号:").append(serviceSelfCertificationWithdraw.getId()).append(",提现处理时出现系统错误:").append(";");
//                }
//            } finally {
//                HeavyUtil.runDone(HeavyKeyEnum.WITHDRAWAL_REQUEST.getCode() + serviceSelfCertificationWithdraw.getId());
//            }
//        }
//        return errorMsg.toString();
    }

    @Override
    public Integer getRunningBatchCount() {

        return custTaskQueueService.notRunningOutOrder(CustTaskQueueCmdEnum.WITHDRAWAL.getCode());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String individualTreatment(AdminSinceCertificationIndividualProcessVo adminSinceCertificationIndividualProcessVo) {
        ServiceSelfCertificationWithdraw widthdrawInfo = new ServiceSelfCertificationWithdraw();
        widthdrawInfo.setId(adminSinceCertificationIndividualProcessVo.getId());
        ServiceSelfCertificationWithdraw widthdrawData = baseMapper.selectById(widthdrawInfo);

        Boolean isUp = false;
        if (!StringUtil.isBlank(adminSinceCertificationIndividualProcessVo.getRemark())) {
            isUp = true;
            widthdrawInfo.setIssuingNote(adminSinceCertificationIndividualProcessVo.getRemark());
        }
        if (!StringUtil.isBlank(adminSinceCertificationIndividualProcessVo.getStatus())) {
            if (SelfWithdrawStatusEnum.getStatusDesc(Integer.valueOf(adminSinceCertificationIndividualProcessVo.getStatus())) != null) {
                if (widthdrawData.getStatus().equals(SelfWithdrawStatusEnum.SUCCESS.getCode()) || widthdrawData.getStatus().equals(SelfWithdrawStatusEnum.IN_DISTRIBUT.getCode())) {
                    return "当前状态不允许进行操作";
                }
                isUp = true;
                widthdrawInfo.setStatus(Integer.valueOf(adminSinceCertificationIndividualProcessVo.getStatus()));
                widthdrawInfo.setPeoplePaid(adminSinceCertificationIndividualProcessVo.getApprovers());
            } else {
                return "状态不正确";
            }
        }
        if (isUp) {
            widthdrawInfo.setUpdatedAt(LocalDateTime.now());
            if (this.updateById(widthdrawInfo)) {
                //单笔提现是否修改状态判断
                if (widthdrawInfo.getStatus() != null) {
                    if (widthdrawInfo.getStatus().equals(SelfWithdrawStatusEnum.SUCCESS.getCode())) {
                        this.withdrawOkSendMessage(widthdrawData, true);
                    }
                }
            } else {
                return "更新失败,请重试";
            }
        }

        return "";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<SinceCertificationPrintApplicationFormVo> printApplicationForm(List<AdminSelfCertificationQueryVo> list) {
        List<SinceCertificationPrintApplicationFormVo> sinceCertificationPrintApplicationFormVoList = new ArrayList<>();
        for (AdminSelfCertificationQueryVo serviceSelfCertificationWithdraw : list) {
            SinceCertificationPrintApplicationFormVo sinceCertificationPrintApplicationFormVo = new SinceCertificationPrintApplicationFormVo();
//            if (CoverChargeEnum.ServiceAccountType.CUSTOMER_TYPE.getPlatform().equals(serviceSelfCertificationWithdraw.getPlatformCode())) {
//                sinceCertificationPrintApplicationFormVo.setPlatform("杭州偕创网络科技有限公司");
//            } else {
            sinceCertificationPrintApplicationFormVo.setPlatform(printApplicationPlatform);
            //}
            sinceCertificationPrintApplicationFormVo.setSystemApplicationNumber(String.valueOf(serviceSelfCertificationWithdraw.getId()));
            sinceCertificationPrintApplicationFormVo.setApplyForDepartment(printApplicationDepartment);

            sinceCertificationPrintApplicationFormVo.setApplicationDate(serviceSelfCertificationWithdraw.getCreatedAt());
            if (serviceSelfCertificationWithdraw.getType().equals(SelfCertificationTypeEnum.SINGLE.getCode())) {
                sinceCertificationPrintApplicationFormVo.setNameReceivingCompany(serviceSelfCertificationWithdraw.getIdcardName());
            } else {
                sinceCertificationPrintApplicationFormVo.setNameReceivingCompany(serviceSelfCertificationWithdraw.getCompanyName());
            }

            sinceCertificationPrintApplicationFormVo.setBankName(serviceSelfCertificationWithdraw.getBankName());
            sinceCertificationPrintApplicationFormVo.setBankAccount(serviceSelfCertificationWithdraw.getBankNo());
            sinceCertificationPrintApplicationFormVo.setPaymentAmountwithCapital(NumberToCN.number2CNMontrayUnit(serviceSelfCertificationWithdraw.getMoney()));
            sinceCertificationPrintApplicationFormVo.setPaymentAmountwithLowercase(String.valueOf(serviceSelfCertificationWithdraw.getMoney()));
            if (serviceSelfCertificationWithdraw.getType().equals(SelfCertificationTypeEnum.SINGLE.getCode())) {
                sinceCertificationPrintApplicationFormVo.setAuthenticationType("个体工商户服务费提现打款");
            } else {
                sinceCertificationPrintApplicationFormVo.setAuthenticationType("企业认证客户服务费提现打款");
            }
            sinceCertificationPrintApplicationFormVo.setAgentIDAndAccountSystem(serviceSelfCertificationWithdraw.getMobile());
            sinceCertificationPrintApplicationFormVoList.add(sinceCertificationPrintApplicationFormVo);
            if (serviceSelfCertificationWithdraw.getIsPrint().equals(SelfWithdrawIsPrintEnum.NOT_TO_PRINT.getCode())) {
                ServiceSelfCertificationWithdraw serviceSelfCertificationWithdraw1 = new ServiceSelfCertificationWithdraw();
                serviceSelfCertificationWithdraw1.setId(serviceSelfCertificationWithdraw.getId());
                serviceSelfCertificationWithdraw1.setIsPrint(SelfWithdrawIsPrintEnum.HAVE_TO_PRINT.getCode());
                this.updateByIdUpTime(serviceSelfCertificationWithdraw1);
            }
        }


        return sinceCertificationPrintApplicationFormVoList;
    }

    @Override
    public AdminSelfCertificationMoneyTotalVo queryCertificationPaidMoneyTotal(String idCode, String name, Integer invoice, String platformCode, Integer status, String startDate, String endDate, Integer type) {
        AdminSelfCertificationMoneyTotalVo result = new AdminSelfCertificationMoneyTotalVo();
        Integer isPrint = null;
        if (status != null) {
            if (status == 30) {
                status = null;
                isPrint = 1;
            }
        }
        BigDecimal moneyTotal = serviceSelfCertificationWithdrawMapper.queryCertificationPaidMoneyTotal(idCode, name, invoice, platformCode, status, startDate, endDate, type, null, isPrint);

        result.setMoneyTotal(moneyTotal);
        return result;
    }

    @Override
    public String allProcessingWithdrawalRecordPaid(String approvers) {
        Integer count = this.getRunningBatchCount();
        if (count > 0) {
            return "有正在执行的全量处理任务，请稍后操作";
        }
        QueryWrapper<ServiceSelfCertificationWithdraw> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", SelfWithdrawStatusEnum.SPASS.getCode());
        Integer num = baseMapper.selectCount(queryWrapper);
        if (num == 0) {
            return "没有需要批量执行的记录";
        }
        List<ServiceSelfCertificationWithdraw> withdrawData = baseMapper.selectList(queryWrapper);
        if (withdrawData.isEmpty()) {
            return "没有需要批量执行的记录";
        }

        return this.withdrawalInsertTim(withdrawData, approvers);
    }

    private String withdrawalInsertTim(List<ServiceSelfCertificationWithdraw> withdrawData, String approvers) {
        LocalDateTime now = LocalDateTime.now();
        StringBuilder errorMsg = new StringBuilder();
        //多线程处理
        for (int i = 0; i < withdrawData.size(); i = i + SPLIT_MAX_NUM) {
            List<ServiceSelfCertificationWithdraw> subapplyList = withdrawData.stream().skip(i).limit(SPLIT_MAX_NUM)
                    .collect(Collectors.toList());
            threadPoolExecutor.execute(() -> {
                for (ServiceSelfCertificationWithdraw widthdrawInfo : subapplyList) {
                    try {
                        if (!HeavyUtil.isRun(HeavyKeyEnum.WITHDRAWAL_REQUEST.getCode() + widthdrawInfo.getId())) {

                            boolean hitWhiteList = false;
                            if (!StringUtils.isEmpty(DepAccountWhiteList)) {
                                List<com.tengju.settlement.domain.model.account.UserIdCode> whiteIdCodeList = Arrays.stream(DepAccountWhiteList.split(","))
                                        .map(Long::parseLong)
                                        .map(com.tengju.settlement.domain.model.account.UserIdCode::new)
                                        .collect(Collectors.toList());
                                hitWhiteList = whiteIdCodeList.contains(new com.tengju.settlement.domain.model.account.UserIdCode(widthdrawInfo.getIdCode()));
                            }

                            //命中白名单 不允许线上打款
                            if (hitWhiteList) {
                                throw ApplicationException.error(ApplicationExceptionCode.WHITE_LIST_MEMBER_NOT_ALLOWED);
                            } else {
                                //存管开户校验
                                DepositoryAccount depositoryAccount = depositoryAccountRepository
                                        .getByIdCodeStatusNormal(new com.tengju.settlement.domain.model.account.UserIdCode(widthdrawInfo.getIdCode()), DepositoryChannel.PING_AN);
                                if (depositoryAccount == null || depositoryAccount.getStatus() != AccountStatus.NORMAL) {
                                    throw ApplicationException.error(ApplicationExceptionCode.DEP_ACCOUNT_NOT_OPEN);
                                }
                            }

                            QueryWrapper<ServiceSelfCertificationWithdraw> wrapper = new QueryWrapper<>();
                            wrapper.eq("id", widthdrawInfo.getId());
                            wrapper.eq("status", widthdrawInfo.getStatus());
                            widthdrawInfo.setStatus(SelfWithdrawStatusEnum.IN_DISTRIBUT.getCode());
                            widthdrawInfo.setUpdatedAt(LocalDateTime.now());
                            widthdrawInfo.setPeoplePaid(approvers);
                            if (this.update(widthdrawInfo, wrapper)) {
                                CustTaskQueue custTaskQueue = new CustTaskQueue();
                                custTaskQueue.setCmd(CustTaskQueueCmdEnum.WITHDRAWAL.getCode());
                                custTaskQueue.setRunningTime(now);
                                Map<String, Object> jsonMap = new LinkedHashMap<String, Object>();
                                jsonMap.put("id", widthdrawInfo.getId());
                                jsonMap.put("admin_id", approvers);
                                JSONObject jsonToString = new JSONObject(jsonMap);
                                custTaskQueue.setArgs(jsonToString.toString());
                                custTaskQueue.setStatus(CustTaskQueueStatusEnum.IS_NOT_RUNN.getCode());
                                custTaskQueue.setCreateTime(now);
                                custTaskQueueService.save(custTaskQueue);
                            } else {
                                errorMsg.append("提现序号:").append(widthdrawInfo.getId()).append(",提现处理时出现系统错误:").append(";");
                                log.error("提现全量处理插入时单笔出现错误:提现id:{};更新失败", widthdrawInfo.getId());
                            }
                        }
                    } catch (Exception e) {
                        errorMsg.append("提现序号:").append(widthdrawInfo.getId()).append(",提现处理时出现系统错误:").append(";");

                        log.error("提现全量处理插入时单笔出现错误:提现id:{}", widthdrawInfo.getId(), e);
                    } finally {
                        HeavyUtil.runDone(HeavyKeyEnum.WITHDRAWAL_REQUEST.getCode() + widthdrawInfo.getId());
                    }
                }
            });
        }
        //单线程处理
//        for (ServiceSelfCertificationWithdraw widthdrawInfo : withdrawData) {
//            try {
//                if(!HeavyUtil.isRun(HeavyKeyEnum.WITHDRAWAL_REQUEST.getCode() + widthdrawInfo.getId())){
//                    CustTaskQueue custTaskQueue = new CustTaskQueue();
//                    custTaskQueue.setCmd(CustTaskQueueCmdEnum.WITHDRAWAL.getCode());
//                    custTaskQueue.setRunningTime(now);
//
//                    Map<String, Object> jsonMap = new LinkedHashMap<String, Object>();
//                    jsonMap.put("id", widthdrawInfo.getId());
//                    jsonMap.put("admin_id", approvers);
//                    JSONObject jsonToString = new JSONObject(jsonMap);
//                    custTaskQueue.setArgs(jsonToString.toString());
//                    custTaskQueue.setStatus(CustTaskQueueStatusEnum.IS_NOT_RUNN.getCode());
//                    custTaskQueue.setCreateTime(now);
//                    custTaskQueueService.save(custTaskQueue);
//                }
//            } catch (Exception e) {
//                log.error("提现全量处理插入时单笔出现错误:提现id:{}", widthdrawInfo.getId(), e);
//            } finally {
//                HeavyUtil.runDone(HeavyKeyEnum.WITHDRAWAL_REQUEST.getCode() + widthdrawInfo.getId());
//            }
//        }
        return errorMsg.toString();
    }

    /**
     * 提现结果查询
     *
     * @param custPaidTransEntry
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CashBackRes doWithdrawalResultsQuery(CustPaidTrans custPaidTransEntry) {


        CashBackRes cashBackRes = new CashBackRes();
        log.info("查询打款请求流水号:{}", custPaidTransEntry.getReqSn());
        ServiceSelfCertificationWithdraw withdrawData = baseMapper.selectById(custPaidTransEntry.getWithdrawId());
//        try {
            Transfer transfer = transferService.findTransfer(new BusinessNo(custPaidTransEntry.getReqSn()));

            custPaidTransEntry.setReturnParams(custPaidTransService.getAddJsonString(custPaidTransEntry.getReturnParams(), transfer));
            custPaidTransEntry.setQueryInfo(custPaidTransService.getAddJsonString(custPaidTransEntry.getQueryInfo(), transfer));

            if (transfer == null) {
                log.error("查询打款请求:{};错误IS:代付系统层.jsonTransferOrderQueryResponse:{}", custPaidTransEntry.getReqSn(), custPaidTransEntry);
                custPaidTransEntry.setReturnParams(custPaidTransService.getAddJsonString(custPaidTransEntry.getReturnParams(), ""));
                custPaidTransEntry.setQueryInfo(custPaidTransService.getAddJsonString(custPaidTransEntry.getQueryInfo(), ""));
                custPaidTransService.updateByReqSn(custPaidTransEntry.getReqSn(), custPaidTransEntry);
                withdrawData.setQueryRemark("查询异常");
                this.updateByIdUpTime(withdrawData);

                cashBackRes.setIsPaymentSystemError(true);
                cashBackRes.setErrorMessage("查询代付系统系统层出现错误,请联系排查,错误信息");

                return cashBackRes;
            } else {
                //单号不存在(只在代付系统异常没有存储单号情况下)
//                if(transferOrderQueryResponse.getCode() == PaymentSystemAbnormalCodeEnum.NUMBER_DOES_NOT_EXIST.getCode()) {
//                    custPaidTransEntry.setStatus(CustPaidTransStatusEnum.SYSTEM_ERROR.getCode());
//                    custPaidTransService.updateByReqSn(custPaidTransEntry.getReqSn(), custPaidTransEntry);
//                    log.error("查询打款请求:{};错误IS:单号不存在.jsonTransferOrderQueryResponse:{}", transferOrderQueryRequest.getBusinessNo(), jsonTransferOrderQueryResponse);
//
//                    withdrawData.setStatus(SelfWithdrawStatusEnum.SPASS.getCode());
//                    withdrawData.setQueryRemark("访问异常,可重新处理");
//                    withdrawData.setRetryCode(String.valueOf(transferOrderQueryResponse.getCode()));
//                    this.updateByIdUpTime(withdrawData);
//
//                    cashBackRes.setIsPaymentSystemError(true);
//                    cashBackRes.setErrorMessage("查询代付系统系统层出现错误,单号不存在:" + jsonTransferOrderQueryResponse.getMsg());
//
//                    return cashBackRes;
//                }
                if (TradeStatus.FAIL == transfer.getTradeStatus()) {
                    custPaidTransEntry.setStatus(CustPaidTransStatusEnum.FAILURE.getCode());
                    custPaidTransService.updateByReqSn(custPaidTransEntry.getReqSn(), custPaidTransEntry);

                    cashBackRes.setIsPaymentSystemThirdPartyError(true);
                    cashBackRes.setErrorMessage("打款失败,错误:" + transfer.getExtra().getChannelRespMessage());
                    withdrawData.setStatus(SelfWithdrawStatusEnum.FAIL.getCode());
                    withdrawData.setQueryRemark("打款失败" + transfer.getExtra().getChannelRespMessage());
                    this.updateByIdUpTime(withdrawData);


                    //回滚冻结金额
                    serviceAccountService.rollbackFreezeBalance(new AccountId(withdrawData.getAccountId()),
                            new com.tengju.settlement.domain.shared.Amount(withdrawData.getMoney()), ProfitTypeEnum.self_withdraw,
                            withdrawData.getId(), null);

                    return cashBackRes;
                }

                if (TradeStatus.PROCESS == transfer.getTradeStatus() || TradeStatus.CREATED == transfer.getTradeStatus()) {
                    custPaidTransEntry.setStatus(CustPaidTransStatusEnum.UNKNOWN.getCode());
                    custPaidTransService.updateByReqSn(custPaidTransEntry.getReqSn(), custPaidTransEntry);
                    cashBackRes.setIsPaymentSystemThirdPartyUnknown(true);
                    cashBackRes.setErrorMessage("第三方返回未知, 请等待查询结果;信息:处理中");
                    withdrawData.setQueryRemark("处理中");
                    this.updateByIdUpTime(withdrawData);

                    return cashBackRes;
                }

                custPaidTransEntry.setStatus(CustPaidTransStatusEnum.UNKNOWN.getCode());
                log.error("查询打款请求:{};错误IS:代付系统业务层.jsonTransferResponse:{}", custPaidTransEntry.getReqSn(), custPaidTransEntry);
                custPaidTransService.updateByReqSn(custPaidTransEntry.getReqSn(), custPaidTransEntry);

                cashBackRes.setIsPaymentSystemError(true);
                cashBackRes.setErrorMessage("查询代付系统业务层出现错误未知错误,请联系排查,错误信息");
                //return cashBackRes;
            }

            if (TradeStatus.SUCCESS == transfer.getTradeStatus()) {

                custPaidTransEntry.setStatus(CustPaidTransStatusEnum.SUCCESSFUL.getCode());
                custPaidTransService.updateByReqSn(custPaidTransEntry.getReqSn(), custPaidTransEntry);

                cashBackRes.setErrorMessage("");
                withdrawData.setQueryRemark("");
                withdrawData.setStatus(SelfWithdrawStatusEnum.SUCCESS.getCode());
                this.updateByIdUpTime(withdrawData);

                try {
                    this.withdrawOkSendMessage(withdrawData, false);
                } catch (Exception e) {
                    log.error("打款已处理完成, 但是消息通知出现错误reqSn:{};{}", this.getReq(withdrawData), e);
                    throw e;
                }

            } else {
                cashBackRes.setIsSystemError(true);
                cashBackRes.setErrorMessage("未知返回异常");
                return cashBackRes;
            }

//        } catch (Exception e) {
//            log.error("自认证打款出现错误reqSn:{};提现id:{};请求信息:{};错误:{}", custPaidTransEntry.getReqSn(), custPaidTransEntry.getWithdrawId(), custPaidTransEntry, e);
//            MsgSendUtil.sendLarkMsg("自认证打款出现错误reqSn:{};提现id:{};请求信息:{};", custPaidTransEntry.getReqSn(), custPaidTransEntry.getWithdrawId(), custPaidTransEntry);
//            cashBackRes.setIsSystemError(true);
//            cashBackRes.setErrorMessage("查询自认证打款出现未知错误,请联系排查");
//
//            return cashBackRes;
//        }


        return cashBackRes;
    }



    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void transferRevoke(String businessNo) {

        CustPaidTrans custPaidTrans = iCustPaidTransService.getReqData(businessNo);
        ServiceSelfCertificationWithdraw withdrawData = baseMapper.selectById(custPaidTrans.getWithdrawId());

        if (SelfWithdrawStatusEnum.FREJECT.getCode().equals(withdrawData.getStatus()) ||
                SelfWithdrawStatusEnum.FAIL.getCode().equals(withdrawData.getStatus()) ||
                SelfWithdrawStatusEnum.CANCEL.getCode().equals(withdrawData.getStatus()) ||
                SelfWithdrawStatusEnum.SREJECT.getCode().equals(withdrawData.getStatus())) {
            return;
        }

        //转账申请记录 置为失败
        custPaidTrans.setStatus(CustPaidTransStatusEnum.FAILURE.getCode());
        custPaidTransService.updateByReqSn(custPaidTrans.getReqSn(), custPaidTrans);

        //发放成功 加余额
        if (SelfWithdrawStatusEnum.SUCCESS.getCode().equals(withdrawData.getStatus()) ||
                SelfWithdrawStatusEnum.SEND.getCode().equals(withdrawData.getStatus())) {
            serviceAccountService.plusBalance(new AccountId(withdrawData.getAccountId()),
                    new com.tengju.settlement.domain.shared.Amount(withdrawData.getMoney()));
        }

        //发放成功 加余额
        if (SelfWithdrawStatusEnum.APPLY.getCode().equals(withdrawData.getStatus()) ||
                SelfWithdrawStatusEnum.FPASS.getCode().equals(withdrawData.getStatus()) ||
                SelfWithdrawStatusEnum.IN_DISTRIBUT.getCode().equals(withdrawData.getStatus())) {
            serviceAccountService.rollbackFreezeBalance(new AccountId(withdrawData.getAccountId()),
                    new com.tengju.settlement.domain.shared.Amount(withdrawData.getMoney()),
                    ProfitTypeEnum.self_withdraw,withdrawData.getId(), null);
        }

        //自认证用户提现记录 置为失败
        withdrawData.setStatus(SelfWithdrawStatusEnum.FAIL.getCode());
        this.updateByIdUpTime(withdrawData);


    }



    /**
     * 进行提现
     *
     * @param id            Integer
     * @param adminNickName String
     * @param isAll         Boolean
     * @return CashBackRes
     */
    @Override
    @Transactional
    public CashBackRes doWithdraw(Integer id, String adminNickName, Boolean isAll) {



        CashBackRes cashBackRes = new CashBackRes();
        cashBackRes.setErrorMessage("");
        QueryWrapper<ServiceSelfCertificationWithdraw> wrapper = new QueryWrapper<>();
        wrapper.eq("id", id);
        ServiceSelfCertificationWithdraw withdrawData = baseMapper.selectOne(wrapper);
        if (withdrawData == null) {
            cashBackRes.setIsBusinessError(true);
            cashBackRes.setErrorMessage("该笔提现记录不存在");
            return cashBackRes;
        }

        DepositoryAccount depositoryAccount =
                depositoryAccountRepository.getByIdCodeStatusNormal(new com.tengju.settlement.domain.model.account.UserIdCode(withdrawData.getIdCode()), DepositoryChannel.PING_AN);
        if (depositoryAccount == null) {
            throw ApplicationException.error(ApplicationExceptionCode.DEP_ACCOUNT_NOT_OPEN);
        }
        List<DepositoryBankCard> bankcards = depositoryBankCardRepository.getByDepositoryAccountIdStatus(
                new com.tengju.settlement.domain.model.account.UserIdCode(withdrawData.getIdCode()),
                depositoryAccount.getDepositoryAccountId(), List.of(BindStatus.SUCCESS));
        if (CollectionUtils.isEmpty(bankcards)) {
            throw ApplicationException.error(ApplicationExceptionCode.DEP_BAND_CARD_NOT_BOUND);
        }

        if (isAll) {
            if (!withdrawData.getStatus().equals(SelfWithdrawStatusEnum.IN_DISTRIBUT.getCode())) {
                cashBackRes.setIsBusinessError(true);
                cashBackRes.setErrorMessage("该笔提现状态不正确:" + SelfWithdrawStatusEnum.getStatusDesc(withdrawData.getStatus()));

                return cashBackRes;
            }
        } else {
            if (!withdrawData.getStatus().equals(SelfWithdrawStatusEnum.SPASS.getCode())) {
                cashBackRes.setIsBusinessError(true);
                cashBackRes.setErrorMessage("该笔提现状态不正确:" + SelfWithdrawStatusEnum.getStatusDesc(withdrawData.getStatus()));

                return cashBackRes;
            }
        }


        String reqSn = this.getReq(withdrawData);

        withdrawData.setStatus(SelfWithdrawStatusEnum.IN_DISTRIBUT.getCode());
        withdrawData.setUpdatedAt(LocalDateTime.now());
        withdrawData.setPeoplePaid(adminNickName);
        withdrawData.setReqSn(reqSn);
        this.updateByIdUpTime(withdrawData);
        ServiceSelfCertification serviceSelfCertificationPo = new ServiceSelfCertification();
        serviceSelfCertificationPo.setId(withdrawData.getSelfCertificationId());
        ServiceSelfCertification serviceSelfCertification = serviceSelfCertificationService.getBaseMapper().selectById(serviceSelfCertificationPo);
        CustPaidTrans custPaidTransEntry = new CustPaidTrans();
        if ("".equals(withdrawData.getRetryCode())) {
            //通联请求记录处理
            //TODO 确认传值
            custPaidTransEntry.setAdminId(adminNickName);
            custPaidTransEntry.setReqSn(reqSn);
            custPaidTransEntry.setAccountNo(withdrawData.getBankNo());
            if (withdrawData.getType().equals(SelfCertificationTypeEnum.SINGLE.getCode())) {
                custPaidTransEntry.setAccountName(serviceSelfCertification.getIdcardName());
            } else {
                custPaidTransEntry.setAccountName(serviceSelfCertification.getCompanyName());
            }
            custPaidTransEntry.setAccountProp(CustPaidTransPropEnum.COMPANY_ACCOUNT.getCode());
            custPaidTransEntry.setAmount(withdrawData.getMoney());
            custPaidTransEntry.setSummary("ABM代理" + withdrawData.getIdCode() + "服务费提现");
            custPaidTransEntry.setWithdrawId(withdrawData.getId());
            custPaidTransEntry.setBankCode("");
            custPaidTransEntry.setCreateTime(LocalDateTime.now());
            custPaidTransEntry.setReturnParams("[]");
            custPaidTransEntry.setQueryInfo("[]");
            custPaidTransEntry.setOpenBank(bankcards.get(0).getBankName());
            custPaidTransEntry.setStatus(CustPaidTransStatusEnum.FOR_QUERY.getCode());

            try {
                if (!custPaidTransService.save(custPaidTransEntry)) {
                    cashBackRes.setIsSystemError(true);
                    cashBackRes.setErrorMessage("提现插入失败");
                    log.error("提现打款系统异常:提现id:{};提现请求查询插入失败", id);

                    return cashBackRes;
                }
            } catch (Exception e) {
                cashBackRes.setIsSystemError(true);
                cashBackRes.setErrorMessage("提现插入失败");
                log.error("提现打款系统异常:提现id:{};提现请求查询插入失败;{}", id, e);
            }
        } else {
            //如果打款出现代付系统请求异常->查询定时任务(单号不存在)->后台操作处理(或批量处理)->走到这里重新改为申请中
            custPaidTransEntry.setStatus(CustPaidTransStatusEnum.FOR_QUERY.getCode());
            if (!custPaidTransService.updateByReqSn(reqSn, custPaidTransEntry)) {
                cashBackRes.setIsSystemError(true);
                cashBackRes.setErrorMessage("提现重试请求插入失败");
                log.error("提现打款系统异常:提现id:{};提现重试请求插入失败", id);

                return cashBackRes;
            }
            custPaidTransEntry = custPaidTransService.getReqData(reqSn);
        }



        //执行渠道代付
        UnionTransferRequest transaction = new UnionTransferRequest(
                new BusinessNo(custPaidTransEntry.getReqSn()),
                new Amount(DoubleCalculator.multiply(custPaidTransEntry.getAmount().doubleValue(), 100).intValue()),
                custPaidTransEntry.getAccountName(),
                custPaidTransEntry.getAccountNo(),
                AccountType.COMPANY,
                custPaidTransEntry.getBankCode(),
                custPaidTransEntry.getOpenBank(),
                CertificationTypeEnum.CERTIFICATION,
                depositoryAccount.getDepositoryId()
        );

//        if ("dev".equals(env) || "test".equals(env)) {
//            //测试需要
//            transaction = new UnionTransferRequest(
//                    new BusinessNo(custPaidTransEntry.getReqSn()),
//                    new Amount(DoubleCalculator.multiply(custPaidTransEntry.getAmount().doubleValue(), 100).intValue()),
//                    "李婉婷",
//                    "6225887839266918",
//                    AccountType.PERSON,
//                    custPaidTransEntry.getBankCode(),
//                    custPaidTransEntry.getOpenBank(),
//                    CertificationTypeEnum.CERTIFICATION
//            );
//        }

        try {
            log.info("打款请求sn:{};请求信息:{}", transaction.getBusinessNo(), transaction);
            UnionTransferResponse jsonTransferResponse = null;
            try {
                jsonTransferResponse = transferService.unionStoreTransfer(transaction);
                custPaidTransEntry.setReturnParams(custPaidTransService.getAddJsonString(custPaidTransEntry.getReturnParams(), jsonTransferResponse));
                custPaidTransEntry.setQueryInfo(custPaidTransService.getAddJsonString(custPaidTransEntry.getQueryInfo(), transaction));
            } catch (Exception e) {
                log.error("打款出现代付系统请求异常:{};提现id:{};请求信息:{};错误:{}", transaction.getBusinessNo(), id, transaction, e);

                MsgSendUtil.sendLarkMsg("打款出现代付系统请求异常:{};提现id:{};请求信息:{}", transaction.getBusinessNo(), id, JsonUtil.toJSONString(transaction));
                custPaidTransEntry.setReturnParams(custPaidTransService.getAddJsonString(custPaidTransEntry.getReturnParams(), jsonTransferResponse));
                custPaidTransEntry.setQueryInfo(custPaidTransService.getAddJsonString(custPaidTransEntry.getQueryInfo(), transaction));
                custPaidTransEntry.setStatus(CustPaidTransStatusEnum.UNKNOWN.getCode());
                custPaidTransService.updateByReqSn(reqSn, custPaidTransEntry);

                cashBackRes.setIsPaymentSystemError(true);
                cashBackRes.setErrorMessage("打款出现代付系统请求异常,未确定是否打款成功请等待查询结果,请稍后查看是否可以重试,多次无果请联系专员");
                if (jsonTransferResponse != null) {
                    withdrawData.setQueryRemark("R:" + jsonTransferResponse.getMsg());
                } else {
                    withdrawData.setQueryRemark("R:未确定是否打款成功请等待查询结果");
                }
                withdrawData.setStatus(SelfWithdrawStatusEnum.IN_DISTRIBUT.getCode());

                this.updateByIdUpTime(withdrawData);

                return cashBackRes;
            }

            log.info("打款代付系统请求:{};返回信息:{}", transaction.getBusinessNo(), jsonTransferResponse);
            if (!jsonTransferResponse.isSuccess()) {
                log.error("打款请求错误:{};IS:代付系统层.jsonTransferResponse:{}", transaction.getBusinessNo(), jsonTransferResponse);
                MsgSendUtil.sendLarkMsg("打款出现代付系统请求异常:{};提现id:{};请求信息:{}", transaction.getBusinessNo(), id, JsonUtil.toJSONString(transaction));
                custPaidTransEntry.setStatus(CustPaidTransStatusEnum.UNKNOWN.getCode());
                custPaidTransService.updateByReqSn(reqSn, custPaidTransEntry);

                cashBackRes.setIsPaymentSystemError(true);
                cashBackRes.setErrorMessage("未确定是否打款成功请等待查询结果.错误信息:" + jsonTransferResponse.getMsg());
                withdrawData.setQueryRemark("S:" + jsonTransferResponse.getMsg() + ";未确定是否打款成功请等待查询结果");
                withdrawData.setStatus(SelfWithdrawStatusEnum.IN_DISTRIBUT.getCode());
                this.updateByIdUpTime(withdrawData);

                return cashBackRes;
            } else {
                if (TradeStatus.FAIL == jsonTransferResponse.getTradeStatus()) {
                    custPaidTransEntry.setStatus(CustPaidTransStatusEnum.FAILURE.getCode());
                    custPaidTransService.updateByReqSn(reqSn, custPaidTransEntry);

                    cashBackRes.setIsPaymentSystemThirdPartyError(true);
                    cashBackRes.setErrorMessage("打款失败,错误:" + jsonTransferResponse.getMsg());
                    withdrawData.setStatus(SelfWithdrawStatusEnum.FAIL.getCode());
                    withdrawData.setQueryRemark(jsonTransferResponse.getMsg());
                    this.updateByIdUpTime(withdrawData);

                    return cashBackRes;
                }

                if (TradeStatus.PROCESS == jsonTransferResponse.getTradeStatus() || TradeStatus.CREATED == jsonTransferResponse.getTradeStatus()) {
                    custPaidTransEntry.setStatus(CustPaidTransStatusEnum.UNKNOWN.getCode());
                    custPaidTransService.updateByReqSn(reqSn, custPaidTransEntry);
                    cashBackRes.setIsPaymentSystemThirdPartyUnknown(true);
                    cashBackRes.setErrorMessage("第三方返回未知, 请等待查询结果;信息:" + jsonTransferResponse.getMsg());
                    withdrawData.setQueryRemark(jsonTransferResponse.getMsg());
                    this.updateByIdUpTime(withdrawData);

                    return cashBackRes;
                }

                log.error("打款请求错误:{};IS:代付系统未知失败状态.jsonTransferResponse:{}", transaction.getBusinessNo(), jsonTransferResponse);

                custPaidTransEntry.setStatus(CustPaidTransStatusEnum.UNKNOWN.getCode());
                custPaidTransService.updateByReqSn(reqSn, custPaidTransEntry);

                cashBackRes.setIsPaymentSystemError(true);
                cashBackRes.setErrorMessage("代付系统业务层出现未知错误,请联系排查;" + jsonTransferResponse.getMsg());
                withdrawData.setQueryRemark("代付系统业务层出现未知错误,请联系排查;" + jsonTransferResponse.getMsg());
                withdrawData.setStatus(SelfWithdrawStatusEnum.IN_DISTRIBUT.getCode());
                this.updateByIdUpTime(withdrawData);

                return cashBackRes;
            }

//            if(TradeStatus.SUCCESS == jsonTransferResponse.getTradeStatus()) {
//                custPaidTransEntry.setStatus(CustPaidTransStatusEnum.SUCCESSFUL.getCode());
//                custPaidTransService.updateByReqSn(reqSn, custPaidTransEntry);
//
//                cashBackRes.setErrorMessage("");
//                withdrawData.setQueryRemark(jsonTransferResponse.getMsg());
//                withdrawData.setStatus(SelfWithdrawStatusEnum.SUCCESS.getCode());
//                withdrawData.setPaymentTime(LocalDateTime.now());
//                this.updateByIdUpTime(withdrawData);
//            } else {
//                custPaidTransEntry.setStatus(CustPaidTransStatusEnum.UNKNOWN.getCode());
//                custPaidTransService.updateByReqSn(reqSn, custPaidTransEntry);
//                withdrawData.setQueryRemark(jsonTransferResponse.getMsg());
//                withdrawData.setStatus(SelfWithdrawStatusEnum.IN_DISTRIBUT.getCode());
//                this.updateByIdUpTime(withdrawData);
//                log.error("打款请求错误:{};IS:代付系统未知成功状态.jsonTransferResponse:{}", transaction.getBusinessNo(), jsonTransferResponse);
//
//                cashBackRes.setIsSystemError(true);
//                cashBackRes.setErrorMessage("未知返回异常");
//                return cashBackRes;
//            }

        } catch (Exception e) {
            log.error("老货款打款出现错误:{};提现id:{};请求信息:{};错误:{}", transaction.getBusinessNo(), id, transaction, e);

            throw e;
        }
//        try {
//            this.withdrawOkSendMessage(withdrawData, false);
//        } catch (Exception e) {
//            log.error("打款已处理完成, 但是消息通知出现错误reqSn:{};{}", this.getReq(withdrawData), e);
//            cashBackRes.setIsSystemError(true);
//            cashBackRes.setErrorMessage("打款已处理完成, 但是消息通知出现错误");
//            throw e;
//        }

        //return cashBackRes;
    }

//    @Transactional
//    @Override
//    public CashBackRes certificationModelResultsNotice(TransferResponse transferResponse) {
//        CashBackRes cashBackRes = new CashBackRes();
//        CustPaidTrans custPaidTransEntry = new CustPaidTrans();
//        ServiceSelfCertificationWithdraw withdrawData = null;
//        try {
//            custPaidTransEntry = custPaidTransService.getReqData(transferResponse.getBusinessNo());
//            if(custPaidTransEntry == null) {
//                log.info("消费自认证提现结果出现未查询到的单子:{}", transferResponse.getBusinessNo());
//                cashBackRes.setIsPaymentSystemThirdPartyError(true);
//                cashBackRes.setErrorMessage("消费自认证提现结果出现未查询到的单子" + transferResponse.getBusinessNo());
//                return cashBackRes;
//            }
//            custPaidTransEntry.setReturnParams(custPaidTransService.getAddJsonString(custPaidTransEntry.getReturnParams(), transferResponse));
//            QueryWrapper<ServiceSelfCertificationWithdraw> wrapper = new QueryWrapper<>();
//            wrapper.eq("id", custPaidTransEntry.getWithdrawId());
//            withdrawData = baseMapper.selectOne(wrapper);
//            if(HeavyUtil.isRun(HeavyKeyEnum.WITHDRAWAL_QUERY.getCode() + withdrawData.getId())) {
//                cashBackRes.setIsPaymentSystemThirdPartyError(true);
//                cashBackRes.setErrorMessage("消费自认证提现结果出现同时处理情况" + transferResponse.getBusinessNo());
//
//                return cashBackRes;
//            }
//            if(!transferResponse.successBizCode()){
//                if(PaymentSystemAgreedChannelStateEnum.FAILURE.getCode().equals(transferResponse.getStatus())) {
//                    custPaidTransEntry.setStatus(CustPaidTransStatusEnum.FAILURE.getCode());
//                    custPaidTransService.updateByReqSn(custPaidTransEntry.getReqSn(), custPaidTransEntry);
//
//                    cashBackRes.setIsPaymentSystemThirdPartyError(true);
//                    cashBackRes.setErrorMessage("打款失败,错误:" + transferResponse.getChannelMessage());
//                    withdrawData.setStatus(SelfWithdrawStatusEnum.FAIL.getCode());
//                    withdrawData.setQueryRemark(transferResponse.getMessage() + transferResponse.getChannelMessage());
//                    this.updateByIdUpTime(withdrawData);
//
//                    return cashBackRes;
//                }
//
//                if(PaymentSystemAgreedChannelStateEnum.PROCESS.getCode().equals(transferResponse.getStatus()) || PaymentSystemAgreedChannelStateEnum.UNKNOW.getCode().equals(transferResponse.getStatus())) {
//                    custPaidTransEntry.setStatus(CustPaidTransStatusEnum.UNKNOWN.getCode());
//                    custPaidTransService.updateByReqSn(transferResponse.getBusinessNo(), custPaidTransEntry);
//                    cashBackRes.setIsPaymentSystemThirdPartyUnknown(true);
//                    cashBackRes.setErrorMessage("第三方返回未知, 请等待查询结果;信息:" + transferResponse.getMessage() + transferResponse.getChannelMessage());
//                    withdrawData.setQueryRemark(transferResponse.getMessage() + transferResponse.getChannelMessage());
//                    this.updateByIdUpTime(withdrawData);
//
//                    return cashBackRes;
//                }
//
//                log.error("打款请求错误:{};IS:代付系统未知失败状态.jsonTransferResponse:{}", transferResponse.getBusinessNo(), transferResponse);
//
//                custPaidTransEntry.setStatus(CustPaidTransStatusEnum.UNKNOWN.getCode());
//                custPaidTransService.updateByReqSn(transferResponse.getBusinessNo(), custPaidTransEntry);
//
//                cashBackRes.setIsPaymentSystemError(true);
//                cashBackRes.setErrorMessage("代付系统业务层出现未知错误,请联系排查;" + transferResponse.getMessage() + transferResponse.getChannelMessage());
//                withdrawData.setQueryRemark("代付系统业务层出现未知错误,请联系排查;" + transferResponse.getMessage() + transferResponse.getChannelMessage());
//                withdrawData.setStatus(SelfWithdrawStatusEnum.IN_DISTRIBUT.getCode());
//                this.updateByIdUpTime(withdrawData);
//
//                return cashBackRes;
//            }
//
//            if(PaymentSystemAgreedChannelStateEnum.SUCCESS.getCode().equals(transferResponse.getStatus())) {
//                custPaidTransEntry.setStatus(CustPaidTransStatusEnum.SUCCESSFUL.getCode());
//                custPaidTransService.updateByReqSn(transferResponse.getBusinessNo(), custPaidTransEntry);
//
//                cashBackRes.setErrorMessage("");
//                withdrawData.setQueryRemark(transferResponse.getMessage() + transferResponse.getChannelMessage());
//                withdrawData.setStatus(SelfWithdrawStatusEnum.SUCCESS.getCode());
//                withdrawData.setPaymentTime(LocalDateTime.now());
//                this.updateByIdUpTime(withdrawData);
//            } else {
//                custPaidTransEntry.setStatus(CustPaidTransStatusEnum.UNKNOWN.getCode());
//                custPaidTransService.updateByReqSn(transferResponse.getBusinessNo(), custPaidTransEntry);
//                withdrawData.setQueryRemark(transferResponse.getMessage() + transferResponse.getChannelMessage());
//                withdrawData.setStatus(SelfWithdrawStatusEnum.IN_DISTRIBUT.getCode());
//                this.updateByIdUpTime(withdrawData);
//                log.error("打款请求错误:{};IS:代付系统未知成功状态.jsonTransferResponse:{}", transferResponse.getBusinessNo(), transferResponse);
//
//                cashBackRes.setIsSystemError(true);
//                cashBackRes.setErrorMessage("未知返回异常");
//
//                return cashBackRes;
//            }
//            this.withdrawOkSendMessage(withdrawData, false);
//        } catch (Exception e) {
//            log.error("老货款打款出现错误:{};提现id:{};请求信息:{};错误:{}", transferResponse.getBusinessNo(), custPaidTransEntry, transferResponse, e);
//
//            throw e;
//        } finally {
//            if(withdrawData != null) {
//                HeavyUtil.runDone(HeavyKeyEnum.WITHDRAWAL_QUERY.getCode() + withdrawData.getId());
//            }
//        }
//
//        return cashBackRes;
//    }

    private void withdrawOkSendMessage(ServiceSelfCertificationWithdraw draw, Boolean isUp) {

        //查询冻结记录
        QueryWrapper<ServiceFrozenDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("biz_id", draw.getId());
        queryWrapper.eq("biz_code", ProfitTypeEnum.self_withdraw);
        ServiceFrozenDetail frozenDetail = serviceFrozenDetailService.getOne(queryWrapper);
        if (frozenDetail == null) {
            throw new ServiceException("找不到该申请冻结金额记录！");
        }
        if (CoverChargeEnum.FreezeStatus.UN_FREEZE.getCode().equals(frozenDetail.getStatus())) {
            throw new ServiceException("该申请冻结金额已解冻,请确认！");
        }
        //冻结金额解冻
        ServiceFrozenDetail updateFrozen = new ServiceFrozenDetail();
        updateFrozen.setId(frozenDetail.getId());
        updateFrozen.setStatus(CoverChargeEnum.FreezeStatus.UN_FREEZE.getCode());
        updateFrozen.setUpdatedBy(draw.getApprovers());
        updateFrozen.setUpdatedTime(LocalDateTime.now());

        //修改账户金额
        serviceAccountService.updateBalanceForSuccess(draw.getAccountId(), draw.getMoney(), ProfitTypeEnum.self_withdraw, draw.getId(), null);
        serviceFrozenDetailService.updateById(updateFrozen);
        if (isUp) {
            ServiceSelfCertificationWithdraw updatedraw = new ServiceSelfCertificationWithdraw();
            //增加发放时间
            updatedraw.setPaymentTime(LocalDateTime.now());
            updatedraw.setId(draw.getId());
            updatedraw.setUpdatedAt(LocalDateTime.now());
            this.updateById(updatedraw);
        }
        UserInfo userInfo = userDocService.searchUserByIdCodeOrMobile(new UserIdCode(draw.getIdCode()), null);


        String url = ConfigUtil.getConfig().getString("is_withdrawal_send_message", "");
        if (!"".equals(url)) {
            try {
                //发送短信
//                String messageContent = "亲爱的ABMer，";
//                Integer templateId = MessageTemplateIdEnum.ABM.getCode();//默认ABM
//
//                if (CoverChargeEnum.ServiceAccountType.CUSTOMER_TYPE.getPlatform().equals(draw.getPlatformCode())) {
//                    //发放成功,发送站内信以及短信
////                    userMessageClient.sendDtServiceFeeMessage(draw.getIdCode(), "服务费发放通知",
////                            "您的服务费申请已发放至尾号为【" + draw.getBankNo().substring(draw.getBankNo().length() - 4) + "】的银行卡，请注意查收。", true, true, false);
//
//                } else {
//                    messageContent = "亲爱的服务商，";
//                    templateId = MessageTemplateIdEnum.DT.getCode();
//                }
//
//                messageContent += "您本月的服务费申请已发放至尾号【" + draw.getBankNo().substring(draw.getBankNo().length() - 4) + "】银行卡，请注意查收。如有其他疑问，请在线咨询ABM客服。";
                smsBizService.sendChargeDistributeSuccess(userInfo.getMobile(), draw.getBankNo().substring(draw.getBankNo().length() - 4));
                //userMessageClient.sendMobileMessageByTemplate(draw.getIdCode(), templateId, messageContent);
            } catch (Exception e) {
                log.error("自认证服务费发放通知出现错误:{},{}", draw, e);
            }
        }

    }

    private void updateByIdUpTime(ServiceSelfCertificationWithdraw withdrawData) {
        withdrawData.setUpdatedAt(LocalDateTime.now());
        baseMapper.updateById(withdrawData);
    }

    /**
     * 获取请求号
     *
     * @param withdrawData
     * @return
     */
    private String getReq(ServiceSelfCertificationWithdraw withdrawData) {
        String reqSn = withdrawData.getReqSn();
        if (StringUtil.isBlank(reqSn)) {
            return this.genReq(withdrawData);
        }
        return withdrawData.getReqSn();
    }

    /**
     * 生成流水号
     *
     * @param withdrawData 提现数据
     * @return java.lang.String
     * @author qumengmeng
     * @description：生成流水号
     * @date 2020/11/4 14:05
     */
    private String genReq(final ServiceSelfCertificationWithdraw withdrawData) {
        DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        String nowStr = LocalDateTime.now().format(format);

        return String.format("%s%s%s", withdrawData.getId(), nowStr, withdrawData.getIdCode());
    }

    @Override
    public Page<AdminSelfCertificationQueryVo> queryPageCertificationPaid(Page page, String idCode, String name, Integer invoice, String platformCode, Integer status, String startDate, String endDate, Integer type) {
        Integer isPrint = null;
        if (status != null) {
            if (status == 30) {
                status = null;
                isPrint = 1;
            }
        }

        List<AdminSelfCertificationQueryVo> querylist = serviceSelfCertificationWithdrawMapper.queryPageCertificationPaid(page, idCode, name, invoice, platformCode, status, startDate, endDate, type, null, isPrint);
        List<UserIdCode> idList = new ArrayList<>();
        List<String> reqSnList = new ArrayList<>();
        for (AdminSelfCertificationQueryVo log : querylist) {
            idList.add(new UserIdCode(log.getIdCode()));
            reqSnList.add(log.getReqSn());
        }
        Map<UserIdCode, UserInfo> userMap = userService.queryUserMap(idList);
        List<CustPaidTrans> custPaidTransList = custPaidTransMapper.getByReqSns(reqSnList);
        Map<String, CustPaidTrans> custPaidTransMap = custPaidTransList.stream()
                .collect(Collectors.toMap(CustPaidTrans::getReqSn, Function.identity()));
        List<DepositoryAccount> pingAnDepositoryAccounts = depositoryAccountRepository.getByIdCodesStatusNormal(idList.stream().map(UserIdCode::getValue)
                .map(com.tengju.settlement.domain.model.account.UserIdCode::new).collect(Collectors.toList()),DepositoryChannel.PING_AN);
        List<DepositoryAccountId> pingAnDepositoryAccountIds = pingAnDepositoryAccounts
                .stream().map(DepositoryAccount::getDepositoryAccountId).collect(Collectors.toList());
        List<DepositoryAccount> internalDepositoryAccounts = depositoryAccountRepository.getByIdCodesStatusNormal(idList.stream().map(UserIdCode::getValue)
                .map(com.tengju.settlement.domain.model.account.UserIdCode::new).collect(Collectors.toList()),DepositoryChannel.INTERNAL);
        List<DepositoryAccountId> internalDepositoryAccountIds = internalDepositoryAccounts
                .stream().map(DepositoryAccount::getDepositoryAccountId).collect(Collectors.toList());


        Map<UserIdCode, DepositoryBankCard> pingAnDepositoryBankCardMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(pingAnDepositoryAccountIds)) {
            List<DepositoryBankCard> pingAnDepositoryBankCards = depositoryBankCardRepository
                    .getByDepositoryAccountIdsStatus(pingAnDepositoryAccountIds, List.of(BindStatus.SUCCESS));
            pingAnDepositoryBankCardMap = pingAnDepositoryBankCards.stream()
                    .collect(Collectors.toMap(depositoryBankCard -> new UserIdCode(depositoryBankCard.getIdCode().getValue()), Function.identity()));
        }

        Map<UserIdCode, DepositoryBankCard> internalDepositoryBankCardMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(internalDepositoryAccountIds)) {
            List<DepositoryBankCard> internalDepositoryBankCards = depositoryBankCardRepository
                    .getByDepositoryAccountIdsStatus(internalDepositoryAccountIds, List.of(BindStatus.SUCCESS));
            internalDepositoryBankCardMap = internalDepositoryBankCards.stream()
                    .collect(Collectors.toMap(depositoryBankCard -> new UserIdCode(depositoryBankCard.getIdCode().getValue()), Function.identity()));
        }


        for (AdminSelfCertificationQueryVo query : querylist) {

            SelfCertificationWithdrawExtra extra =
                    JsonUtil.toObject(query.getExtra(), SelfCertificationWithdrawExtra.class);

            CustPaidTrans custPaidTrans = custPaidTransMap.get(query.getReqSn());
            DepositoryBankCard depositoryBankCard;
            if (extra != null && extra.getChannel() == DepositoryChannel.INTERNAL) {
                depositoryBankCard = internalDepositoryBankCardMap.get(new UserIdCode(query.getIdCode()));
            } else {
                depositoryBankCard = pingAnDepositoryBankCardMap.get(new UserIdCode(query.getIdCode()));
            }

//            DepositoryAccount depositoryAccount = depositoryAccountMap.get(new UserIdCode(query.getIdCode()));
            if (SelfWithdrawStatusEnum.APPLY.getCode().equals(query.getStatus())
                    || SelfWithdrawStatusEnum.FPASS.getCode().equals(query.getStatus())
                    || SelfWithdrawStatusEnum.FREJECT.getCode().equals(query.getStatus())
                    || SelfWithdrawStatusEnum.CANCEL.getCode().equals(query.getStatus())
                    || SelfWithdrawStatusEnum.SREJECT.getCode().equals(query.getStatus())
                    || SelfWithdrawStatusEnum.SPASS.getCode().equals(query.getStatus())
                    || SelfWithdrawStatusEnum.IN_DISTRIBUT.getCode().equals(query.getStatus())
                    || SelfWithdrawStatusEnum.SEND.getCode().equals(query.getStatus())) {
                query.setBankName(Optional.ofNullable(depositoryBankCard).map(DepositoryBankCard::getBankName).orElse(""));
                query.setBankNo(Optional.ofNullable(depositoryBankCard).map(DepositoryBankCard::getCardNo).orElse(""));
            } else {
                query.setBankName(Optional.ofNullable(custPaidTrans).map(CustPaidTrans::getOpenBank).orElse(""));
                query.setBankNo(Optional.ofNullable(custPaidTrans).map(CustPaidTrans::getAccountNo).orElse(""));
                query.setIdcardName(Optional.ofNullable(custPaidTrans).map(CustPaidTrans::getAccountName).orElse(""));
            }


            UserIdCode userId = new UserIdCode(query.getIdCode());
            if (userMap.containsKey(userId)) {
                UserInfo userVO = userMap.get(userId);
                query.setMobile(userVO.getMobile());
                query.setName(userVO.getName());
            }
            query.setChannel(Optional.ofNullable(extra).map(SelfCertificationWithdrawExtra::getChannel).map(DepositoryChannel::getDesc).orElse(""));
        }
        page.setRecords(querylist);
        return page;
    }

    @Override
    public Page<AdminSelfCertificationQueryVo> queryPageCertificationPaid(Page page, String idCode, String name, Integer invoice, String platformCode, Integer status, String startDate, String endDate, Integer type, String id) {
        List<AdminSelfCertificationQueryVo> querylist = serviceSelfCertificationWithdrawMapper.queryPageCertificationPaid(page, idCode, name, invoice, platformCode, status, startDate, endDate, type, id, null);
        List<UserIdCode> idList = new ArrayList<>();
        List<String> reqSnList = new ArrayList<>();
        for (AdminSelfCertificationQueryVo log : querylist) {
            idList.add(new UserIdCode(log.getIdCode()));
            reqSnList.add(log.getReqSn());
        }
        Map<UserIdCode, UserInfo> userMap = userService.queryUserMap(idList);
        List<CustPaidTrans> custPaidTransList = custPaidTransMapper.getByReqSns(reqSnList);
        Map<String, CustPaidTrans> custPaidTransMap = custPaidTransList.stream()
                .collect(Collectors.toMap(CustPaidTrans::getReqSn, Function.identity()));

        for (AdminSelfCertificationQueryVo query : querylist) {

            CustPaidTrans custPaidTrans = custPaidTransMap.get(query.getReqSn());

            query.setBankName(Optional.ofNullable(custPaidTrans).map(CustPaidTrans::getOpenBank).orElse(""));
            query.setBankNo(Optional.ofNullable(custPaidTrans).map(CustPaidTrans::getAccountNo).orElse(""));
            query.setIdcardName(Optional.ofNullable(custPaidTrans).map(CustPaidTrans::getAccountName).orElse(""));

            UserIdCode userId = new UserIdCode(query.getIdCode());
            if (userMap.containsKey(userId)) {
                UserInfo userVO = userMap.get(userId);
                query.setMobile(userVO.getMobile());
                query.setName(userVO.getName());
            }
        }
        page.setRecords(querylist);
        return page;
    }


}
